package tbs.framework.utils;

import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.extra.spring.SpringUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import tbs.framework.interfaces.FunctionWithThrows;
import tbs.framework.utils.holders.SingletonHolder;

import java.util.Map;
import java.util.regex.Pattern;

/**
 * Bean操作工具类。 提供了注册、装配和销毁Bean等功能。
 *
 * @author abstergo
 */
public class BeanUtil {

    public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz, boolean ignoreNull,
        CopyOptions copyOptions) {
        return cn.hutool.core.bean.BeanUtil.mapToBean(map, clazz, ignoreNull, copyOptions);
    }

    /**
     * 注册并自动装配一个Bean。
     *
     * @param bean     要注册的对象实例
     * @param beanName Bean名称
     */
    public static void registerBean(Object bean, String beanName) {
        autowireBean(bean);
        SpringUtil.registerBean(beanName, bean);
    }

    /**
     * 自动装配一个Bean。
     *
     * @param bean 要装配的对象实例
     */
    public static void autowireBean(Object bean) {
        AutowireCapableBeanFactory autowireCapableBeanFactory =
            SpringUtil.getApplicationContext().getAutowireCapableBeanFactory();
        autowireCapableBeanFactory.autowireBean(bean);
    }

    /**
     * 根据匹配表达式销毁指定类型的Bean。
     *
     * @param beanPattern 匹配Bean名称的正则表达式
     * @param beanClass   Bean的类型
     */
    public static void destroyBean(String beanPattern, Class<?> beanClass) {
        Pattern pattern = Pattern.compile(beanPattern);
        for (Map.Entry<String, ?> entry : SpringUtil.getBeansOfType(beanClass).entrySet()) {
            if (pattern.matcher(entry.getKey()).matches()) {
                AutowireCapableBeanFactory factory = SpringUtil.getApplicationContext().getAutowireCapableBeanFactory();
                factory.destroyBean(entry.getValue());
            }
        }
    }

    /**
     * 从属性构建Bean。
     *
     * @param <T>         泛型类型
     * @param defaultBean 默认Bean实例
     * @param property    属性类型
     * @param func        构建逻辑函数
     * @return 构建后的Bean实例
     * @throws Exception 如果构建失败抛出异常
     */
    public static <T> T buildBeanFromProperties(T defaultBean, Class<? extends T> property,
        FunctionWithThrows<Class<? extends T>, T, Exception> func) throws Throwable {
        if (func == null) {
            func = BeanUtil::useEmptyArgs;
        }
        if (property == null) {
            return defaultBean;
        }
        T bean = func.apply(property);
        return bean;
    }

    /**
     * 使用无参构造方法创建对象实例。
     *
     * @param <T> 泛型类型
     * @param p   类型
     * @return 创建的新实例
     * @throws Exception 如果构造失败抛出异常
     */
    public static <T> T useEmptyArgs(Class<? extends T> p) throws Exception {
        return p.getConstructor().newInstance();
    }

    /**
     * 强制类型转换。
     *
     * @param <T>  泛型类型
     * @param <T1> 目标泛型类型
     * @param v    要转换的对象
     * @return 转换后的对象
     */
    public static <T, T1 extends T> T1 getAs(T v) {
        return (T1)v;
    }

    /**
     * 检查对象是否为指定基类或接口的实例。
     *
     * @param value 对象实例
     * @param base  基类或接口类型
     * @return 如果是返回对象实例，否则返回null
     */
    public static <T> T getIfBase(@NotNull Object value, @NotNull Class<T> base) {
        return isBaseFrom(value.getClass(), base) ? (T)value : null;
    }

    /**
     * 判断一个类是否是另一个类或接口的子类或实现类。
     *
     * @param target 目标类
     * @param base   基类或接口
     * @return 如果target是base的子类或实现类返回true，否则false
     */
    public static final boolean isBaseFrom(@NotNull Class<?> target, @NotNull Class<?> base) {
        return base.isAssignableFrom(target);
    }
    /**
     * 获取指定类型的Bean实例。
     *
     * @param <T>   泛型类型
     * @param clazz Bean类型
     * @return 指定类型的Bean实例
     */
    public static final <T> T getBean(Class<? extends T> clazz) {
        return SingletonHolder.getInstance(clazz);
    }
}
